package com.rejuvee.myloginapplication.data;

import com.rejuvee.myloginapplication.data.model.LoggedInUser;

/**
 * 远程数据源持有器
 * <p>
 * 本类请求来自远程数据源的身份验证和用户信息
 * <p>
 * 维护用于登录状态和用户凭据信息的内存缓存。
 */
public class LoginRepository {
    // 本类实例引用
    private static volatile LoginRepository instance;
    // 用户数据源（远程）引用
    private final LoginDataSource dataSource;
    // 用户凭据信息(本地)的内存缓存引用
    private LoggedInUser user = null;

    /**
     * 单例访问：私有构造函数
     *
     * @param dataSource 用户数据源（远程）
     */
    private LoginRepository(LoginDataSource dataSource) {
        this.dataSource = dataSource;
    }

    /**
     * 单例访问：获取本实例 并初始化
     *
     * @param dataSource 用户数据源
     * @return 本类实例引用
     */
    public static LoginRepository getInstance(LoginDataSource dataSource) {
        if (instance == null) {
            // 第一次调用此方法时，instance为null， 创建本类实例
            instance = new LoginRepository(dataSource);
        }
        // 多次调用此方法，只返回第一次调用时创建的实例
        return instance;
    }

    /**
     * 如果当前用户凭据不为空，则认为是已经登录的
     *
     * @return true 已登录 false 未登录
     */
    public boolean isLoggedIn() {
        return user != null;
    }

    /**
     * 登录方法
     *
     * @param username 账号
     * @param password 密码
     * @return 网络返回的结果
     */
    public Result<LoggedInUser> login(String username, String password) {
        // handle login
        Result<LoggedInUser> result = dataSource.login(username, password);
        if (result instanceof Result.Success) {
            // 远程登录结果为成功,需保存
            saveLoggedInUser(((Result.Success<LoggedInUser>) result).getData());
        }
        // 成功失败都统一返回，由后面流程处理
        return result;
    }

    /**
     * 登出方法
     */
    public void logout() {
        // 清理用户凭据内存缓存
        user = null;
        // 调用远程数据源，进行登出操作
        dataSource.logout();
    }

    /**
     * 设置登录用户凭据，保存至内存
     *
     * @param user 用户凭据
     */
    private void saveLoggedInUser(LoggedInUser user) {
        this.user = user;
        // If user credentials will be cached in local storage, it is recommended it be encrypted
        // @see https://developer.android.com/training/articles/keystore
    }
}